package com.tiger.admin.http.common.member;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.tiger.admin.Db;
import com.tiger.admin.SaveOperateLog;
import com.tiger.admin.http.common.member.dto.AddDto;
import com.tiger.admin.http.common.member.dto.ChangePwdDto;
import com.tiger.admin.http.common.member.dto.PageDto;
import com.tiger.admin.http.common.member.dto.UpdateInfoDto;
import com.tiger.admin.http.common.member.type.MemberRes;
import com.tiger.admin.dto.PaginationResult;
import com.tiger.admin.http.encipher.EncipherService;
import com.tiger.db.entity.*;
import com.tiger.utils.ResponseUtil;
import com.tiger.utils.Utils;
import jakarta.servlet.http.HttpSession;
import org.springframework.beans.BeanUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.time.Instant;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


@RestController
@RequestMapping("/member")
public class MemberController {
    private final MemberService memberService;
    private final Db db;

    private final EncipherService encipherService;

    public MemberController(MemberService memberService, Db db, EncipherService encipherService) {
        this.memberService = memberService;
        this.db = db;
        this.encipherService = encipherService;
    }

    @PostMapping("page")
    public Object page(@RequestBody PageDto page, @RequestAttribute("memberId") long memberId) {
        PaginationResult<MemberRes> result = new PaginationResult<>();

        QueryWrapper<Member> wrapper = new QueryWrapper<>();

        Member member = db.member.getOne(new QueryWrapper<Member>().select("can_super", "id", "belong").eq("id", memberId));

        //是超级管理员
        if(member.isCanSuper()) {
            wrapper.eq("belong", 0);
        }else {
            wrapper.eq("creator_id", memberId);
        }



        if(page.getAccount() != null && !page.getAccount().isEmpty()) {
            wrapper.like("account", page.getAccount());
        }

        if(page.getName() != null && !page.getName().isEmpty()) {
            wrapper.like("name", page.getName());
        }

        long total = db.member.count(wrapper);
        if(total > 0) {
            result.setTotal(total);

            wrapper.orderByDesc("id");
            wrapper.select("id", "account", "name", "roles", "can_super", "enable", "remark", "tel");

            List<MemberRes> resRows = new ArrayList<>();
            List<Member> rows = db.member.pagination(wrapper, page.getPageNo(), page.getPageSize());

            List<Long> roleIds = new ArrayList<>();

            for(Member row : rows) {
                Long[] roles = row.getRoles();
                if(roles != null && roles.length > 0) {
                    for(Long id : roles) {
                        if(!roleIds.contains(id)) {
                            roleIds.add(id);
                        }
                    }
                }

                MemberRes res = new MemberRes();
                BeanUtils.copyProperties(row, res);
                resRows.add(res);
            }

            if(!roleIds.isEmpty()) {
                QueryWrapper<Role> queryWrapper = new QueryWrapper<>();
                queryWrapper.select("id", "name");
                List<Role> roles = db.role.list(roleIds.size() == 1 ? queryWrapper.eq("id", roleIds.get(0)) : queryWrapper.in("id", roleIds));

                if(!roles.isEmpty()) {
                    Map<Long, String> roleMap = new HashMap<>();
                    for(Role role : roles) {
                        roleMap.put(role.getId(), role.getName());
                    }


                    for(MemberRes row : resRows) {
                        Long[] ids = row.getRoles();

                        if(ids != null && ids.length > 0) {
                            ArrayList<String> names = new ArrayList<>();
                            for(Long id : ids) {
                                if(roleMap.containsKey(id)) {
                                    names.add(roleMap.get(id));
                                }
                            }
                            row.setRoleNames(names);
                        }
                    }
                }

            }


            result.setRows(resRows);
        }


        return ResponseUtil.successRes(result);
    }


    @SaveOperateLog("新增成员")
    @PostMapping("add")
    public Object add(@RequestBody @Validated AddDto data, @RequestAttribute("memberId") long memberId) {
        Member member = new Member();

        Integer userRole = data.getUserRole();
        if(userRole == 1) {
            Teacher teacher = db.teacher.getById(data.getSourceId());
            member.setAccount(teacher.getGh());
            member.setName(teacher.getName());
        }else if(userRole == 2) {
            Student student = db.student.getById(data.getSourceId());
            member.setAccount(student.getXh());
            member.setName(student.getName());
        }else if(userRole == 3) {
            OtherUser otherUser = db.otherUser.getById(data.getSourceId());
            member.setAccount(otherUser.getGh());
            member.setName(otherUser.getName());
        }else {
            return null;
        }

        member.setSource(userRole);
        member.setEnable(data.getEnable());

        if(data.getRoles() != null && data.getRoles().length > 0) {
            member.setRoles(data.getRoles());
        }




        if(db.member.exists(new QueryWrapper<Member>().eq("account", member.getAccount()))) {
            return ResponseUtil.failRes("已存在相同的账号");
        }


        Instant now = Instant.now();

        member.setCreateTime(now.getEpochSecond());
        member.setCreatorId(memberId);

        boolean r = db.member.save(member);

        return r ? ResponseUtil.successRes(data) : ResponseUtil.failRes();

    }


//    @SaveOperateLog("新增成员")
//    @PostMapping("add")
//    public Object add(@RequestBody @Validated Member data, @RequestAttribute("memberId") long memberId) {
//        if(db.member.exists(new QueryWrapper<Member>().eq("account", data.getAccount()))) {
//            return ResponseUtil.failRes("已存在相同的账号");
//        }
//
//        String salt = memberService.generateSalt();
//        data.setSalt(salt);
//        data.setPassword(memberService.buildPassword(data.getPassword(), data.getSalt()));
//
//
//        Instant now = Instant.now();
//
//        data.setCreateTime(now.getEpochSecond());
//        boolean r = db.member.save(data);
//
//        return r ? ResponseUtil.successRes(data) : ResponseUtil.failRes();
//
//    }

    @SaveOperateLog("更新成员")
    @PostMapping("update/{id}")
    public Object add(@RequestBody @Validated Member data, @PathVariable Long id, @RequestAttribute("memberId") long memberId) {
        Member row = db.member.getById(id);
        if(row == null || row.isCanSuper()) return ResponseUtil.successRes();


        Instant now = Instant.now();

        Utils.copyPropertiesIgnoreNull(data, row);

        row.setUpdateTime(now.getEpochSecond());


        boolean r = db.member.updateById(row);

        return r ? ResponseUtil.successRes(row) : ResponseUtil.failRes();

    }

    @SaveOperateLog("删除成员")
    @PostMapping("delete/{id}")
    public Object del(@PathVariable long id, @RequestAttribute("memberId") long memberId) {
        Member row = db.member.getOne(new QueryWrapper<Member>().select("id", "can_super").eq("id", id));

        if(row == null || row.isCanSuper()) return ResponseUtil.successRes();
        boolean r = db.member.removeById(id);
        return r ? ResponseUtil.successRes() : ResponseUtil.failRes();
    }

    //获取用户有权限的菜单
    @GetMapping("permission/menu")
    public Object permissionMenu(@RequestAttribute("memberId") Long memberId) {
        return ResponseUtil.successRes(memberService.permissionMenu(memberId, "id", "name", "parent_id"));
    }

    @SaveOperateLog("修改密码")
    @PostMapping("changePwd")
    public Object changePwd(@RequestBody @Validated ChangePwdDto data, @RequestAttribute("memberId") long memberId, HttpSession session) {
        Member member = db.member.getById(memberId);

        String oldPwd = encipherService.decrypt(session, data.getOldpassword());
        String pwd = encipherService.decrypt(session, data.getPassword());


        if(oldPwd == null || pwd == null) return ResponseUtil.failRes();

        if(!Objects.equals(memberService.buildPassword(oldPwd, member.getSalt()), member.getPassword())) {
            return ResponseUtil.failRes("原密码错误");
        }

        String regex = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d).{8,}$";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(pwd);
        if(!matcher.matches()) return ResponseUtil.failRes("密码必须同时包含大小写字母和数字，且不少于8位");

        if(oldPwd.equals(pwd)) return ResponseUtil.failRes("新旧密码不可以相同");

        String salt = memberService.generateSalt();
        member.setSalt(salt);
        member.setPassword(memberService.buildPassword(pwd, salt));

        boolean r = db.member.updateById(member);

        return r ? ResponseUtil.successRes() : ResponseUtil.failRes();

    }


    @SaveOperateLog("修改个人信息")
    @PostMapping("updateinfo")
    public Object add(@RequestBody UpdateInfoDto dto, @RequestAttribute("memberId") long memberId) {

        Member member = db.member.getOne(new LambdaQueryWrapper<Member>().eq(Member::getId, memberId));

        Utils.copyPropertiesIgnoreNull(dto, member);

        boolean r = db.member.updateById(member);

        return r ? ResponseUtil.successRes() : ResponseUtil.failRes();

    }
}
